package com.lyeducation.services.pay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lyeducation.controllers.dto.OrderDTO;
import com.lyeducation.controllers.dto.PayNotifyDTO;
import com.lyeducation.controllers.dto.PayRequestDTO;
import com.lyeducation.entities.order.OrderMaster;
import com.lyeducation.enums.PayStatusEnum;
import com.lyeducation.enums.ResultEnum;
import com.lyeducation.exception.LeadingEagleException;
import com.lyeducation.repository.OrderMasterRepository;
import com.lyeducation.services.order.OrderService;
import com.lyeducation.services.order.UserOrderServiceImpl;
import com.lyeducation.util.HttpUtil;
import com.lyeducation.util.Md5Utils;
import com.lyeducation.vo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName PayServiceImpl @Description @Author Sky1in3 @Date 2019/1/21 16:12 @Version 1.0
 */
@Service
@Slf4j
public class PayServiceImpl implements PayService {

    private static final String ORDER_NAME = "领鹰国际书院课程订单";

    private static final String LEADING_EAGLE_SALT = "TEVBRElOR19FQUdMRQ==";

    private static final String LEADING_EAGLE_APPID = "2019010702192019117";

    private static final String SUCCESS_RETURN_CODE = "SUCCESS";

    @Autowired
    private LYBestPayServiceImpl lyBestPayService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserOrderServiceImpl userOrderService;

    @Autowired
    private OrderMasterRepository orderMasterRepository;

    @Autowired
    protected HttpServletRequest request;

    /**
     * 发起订单支付
     */
    @Override
    public ResultVO create(OrderDTO orderDTO) {
        OrderMaster orderMaster = orderMasterRepository.getOne(orderDTO.getOrderId());
        // 发起支付前，先查询订单状态是否是未支付状态
        if (!PayStatusEnum.WAIT.getCode().equals(orderMaster.getPayStatus())) {
            log.error("【系统通知】 订单支付状态不正确， orderId={}", orderMaster.getOrderId());
            throw new LeadingEagleException(ResultEnum.ORDER_STATUS_ERROR);
        }

        ResultVO resultVO = new ResultVO();

        PayRequestDTO payRequestDTO = new PayRequestDTO();

        String url = "http://localhost:8080/pay/wxpay/jsApi";
        payRequestDTO.setOpenId(orderDTO.getBuyerOpenid());

        //        Cookie[] cookies = request.getCookies();
        //        String lyHost = null;
        //        for (Cookie cookie : cookies) {
        //            String name = cookie.getName();
        //            String value = cookie.getValue();
        //            if ("ly-host".equals(name)) {
        //                lyHost = value;
        //            }
        //        }
        //        if ("1-ali".equals(lyHost)) {
        //            url = "http://localhost:8080/pay/alipay/pagepay";
        //        } else if ("1-jsapi".equals(lyHost)) {
        //            url = "http://localhost:8080/pay/wxpay/jsApi";
        //            payRequestDTO.setOpenId(orderDTO.getBuyerOpenid());
        //        } else if ("1-qrcode".equals(lyHost)) {
        //            url = "http://localhost:8080/pay/wxpay/qrCode";
        //            payRequestDTO.setOpenId(orderDTO.getBuyerOpenid());
        //        }

        payRequestDTO.setAppId(LEADING_EAGLE_APPID);
        payRequestDTO.setOutTradeNo(orderDTO.getOrderId());
        payRequestDTO.setSubject(ORDER_NAME);
        payRequestDTO.setTotalAmount(String.valueOf(orderMaster.getOrderAmount().intValue()));
        payRequestDTO.setSpbillCreateIp("127.0.0.1");
        payRequestDTO.setTimeoutExpress("24h");
        String json = Md5Utils.setSignWithJsonObj(payRequestDTO, LEADING_EAGLE_SALT);
        System.out.println("签名：" + json);
        String resultStr = null;
        try {
            resultStr = HttpUtil.doPut(url, json);
            System.out.println(resultStr);
            resultVO.setData(resultStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 发起支付就把支付状态改成支付中，避免订单重复提交
        orderMaster.setPayStatus(PayStatusEnum.EXECUTING.getCode());
        OrderMaster updateResult = orderMasterRepository.save(orderMaster);
        if (updateResult == null) {
            log.error("【系统通知】订单状态更新失败, orderMaster={}", orderMaster);
            throw new LeadingEagleException(ResultEnum.ORDER_UPDATE_FAIL);
        }

        return resultVO;
    }

    /**
     * 支付异步回调处理
     */
    @Override
    public String notify(String notify) {
        // 1. 验证签名
        // 2. 支付的状态
        // 3. 支付金额
        // 4. 支付人(下单人 == 支付人)

        // string转成json
        JSONObject jsStr = JSONObject.parseObject(notify);

        // json转成对象
        PayNotifyDTO payNotifyDTO = JSONObject.toJavaObject(jsStr, PayNotifyDTO.class);

        // 查询订单
        OrderDTO orderDTO = orderService.findOne(payNotifyDTO.getOrderId());

        // 判断订单是否存在
        if (orderDTO == null) {
            log.error("【微信支付】异步通知, 订单不存在, orderId={}", payNotifyDTO.getOrderId());
            throw new LeadingEagleException(ResultEnum.ORDER_NOT_EXIST);
        }

        // 获取参数请求签名
        String requestSign = payNotifyDTO.getSign();

        // 获取参数有效签名
        PayNotifyDTO payNotify = new PayNotifyDTO();
        payNotify.setOrderId(orderDTO.getOrderId());
        payNotify.setResultCode(SUCCESS_RETURN_CODE);
        payNotify.setTotalFee(String.valueOf(orderDTO.getOrderAmount().intValue()));
        String json = Md5Utils.setSignWithJsonObj(payNotify, LEADING_EAGLE_SALT);
        payNotify = JSON.parseObject(json, PayNotifyDTO.class);
        String sign = payNotify.getSign();

        // 验证签名
        if (!requestSign.equals(sign)) {
            log.error(
                    "【微信支付】异步通知, 回调签名不一致, orderId={}, 参数请求签名={}, 参数有效签名={}",
                    payNotifyDTO.getOrderId(),
                    payNotifyDTO.getSign(),
                    payNotify.getSign());
            throw new LeadingEagleException(ResultEnum.WXPAY_NOTIFY_SIGN_VERIFY_ERROR);
        }
        log.info("参数请求签名={}, 参数有效签名={}", sign, requestSign);

        // 判断金额是否一致
        if (!String.valueOf(orderDTO.getOrderAmount().intValue()).equals(payNotifyDTO.getTotalFee())) {
            log.error(
                    "【微信支付】异步通知, 订单金额不一致, orderId={}, 微信通知金额={}, 系统金额={}",
                    payNotifyDTO.getOrderId(),
                    payNotifyDTO.getTotalFee(),
                    orderDTO.getOrderAmount());
            throw new LeadingEagleException(ResultEnum.WXPAY_NOTIFY_MONEY_VERIFY_ERROR);
        }

        // 修改订单的支付状态
        userOrderService.paid(orderDTO);

        return SUCCESS_RETURN_CODE;
    }

    /**
     * 支付同步回调处理
     */
    @Override
    public String payReturn(String payReturn) {
        return SUCCESS_RETURN_CODE;
    }

    /**
     * 退款
     */
    @Override
    public String refund(String orderId) {
        OrderMaster orderMaster = orderMasterRepository.getOne(orderId);
        if (orderMaster.getPayStatus().equals(PayStatusEnum.REFUND_WAIT.getCode())) {
            String url = "http://localhost:8080/pay/refuse";
            PayRequestDTO payRequestDTO = new PayRequestDTO();
            //            payRequestDTO.setAppId("2019010702192019117");
            payRequestDTO.setOutTradeNo(orderMaster.getOrderId());
            //            payRequestDTO.setSubject("领鹰国际书院课程退款单");
            //
            // payRequestDTO.setTotalAmount(String.valueOf(orderMaster.getOrderAmount().intValue()));
            //            payRequestDTO.setTimeoutExpress("24h");
            String json = Md5Utils.setSignWithJsonObj(payRequestDTO, "TEVBRElOR19FQUdMRQ==");
            System.out.println(json);
            String resultStr = null;
            try {
                resultStr = HttpUtil.doPut(url, json);
                System.out.println(resultStr);
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 退款成功，修改订单的支付状态为3（已退款）
            orderMaster.setPayStatus(PayStatusEnum.REFUNDED.getCode());
            orderMasterRepository.save(orderMaster);

            return resultStr;
        }
        return ResultEnum.ORDER_PAY_STATUS_ERROR.getMessage();
  }
}
